package com.youngjun.common.security.filter;

import com.youngjun.common.security.service.RequestMapService;
import com.youngjun.common.util.SpringUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.server.MethodNotAllowedException;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;


public class RequestFilter implements Filter {

   private final static Logger logger = LoggerFactory.getLogger(RequestFilter.class);

   private static final HttpMethod [] ALLOW_HTTP_METHODS = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};

   @Override
   public void init(FilterConfig filterConfig) throws ServletException {

   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       HttpServletRequest httpServletRequest = (HttpServletRequest) request;

       /**
        * 是否是允许的请求方法
        */
       if (Arrays.stream(ALLOW_HTTP_METHODS).noneMatch(i -> i.equals(HttpMethod.valueOf(httpServletRequest.getMethod())))){
           logger.error("Request method '" + httpServletRequest.getMethod() + "' not supported");
           throw new MethodNotAllowedException(httpServletRequest.getMethod(), Collections.singletonList(HttpMethod.POST));
       }

       ServletRequest requestWrapper = null;
       MediaType contentType = null;
       String contentTypeStr = httpServletRequest.getContentType();

       if (contentTypeStr != null) {
           contentType = MediaType.valueOf(contentTypeStr);
       }

       RequestMapService requestMapService = SpringUtils.getBean(RequestMapService.class);

        if (MediaType.APPLICATION_JSON_UTF8.equals(contentType)
                &&requestMapService.mustRequestDataFilter(httpServletRequest.getServletPath(),httpServletRequest.getMethod())) {

            byte[] data = null;
            try (InputStream inputStream = request.getInputStream()){
                data = IOUtils.toByteArray(inputStream);
            }
            requestWrapper = new HttpServletRequestWritableWrapper(httpServletRequest, data);
        }

       if (null == requestWrapper) {
           chain.doFilter(request, response);
       } else {
           chain.doFilter(requestWrapper, response);
       }
   }

   @Override
   public void destroy() {

   }
}
